<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<script>
// 2023.7.27 快手一面
/*
    返回obj对象的拷贝对象（的字符串），但是key是通过sort函数排序后的
    之所以转成字符串，主要还是想通过Set进行去重，自然需要普通数据类型
*/
const sortedKeyString = (obj) => {
    let result = {};
    Object.keys(obj).sort((a, b) => {
        return a > b ? -1 : 1;
    }).forEach((key) => {
        result[key] = obj[key];
    })
    return JSON.stringify(result);
}
// 先用set去重，最后再把Set转成数组即可（还需要数组的每一项JSON.parse）
const unique = (arr) => {
    const uniqueSet = new Set(arr.map(obj => sortedKeyString(obj)));
    return Array.from(uniqueSet).map(string => JSON.parse(string));
}
const arr = [
    {
        a: 1,
        b: 2,
    },
    {
        // 与上面的对象重复
        b: 2,
        a: 1,
    },
    {
        c: 1
    },
    {
        a: "1",
        b: 2
    }
]
// 方法二，两两比较
const isEqual = (obj1, obj2) => { // 比较两个对象是否相同
    if(Object.keys(obj1).length !== Object.keys(obj2).length) return false; // 首先属性数量相同
    let obj1keys = Object.keys(obj1);
    let obj2keys = Object.keys(obj2);
    for(let i = 0; i < obj1keys.length; i ++ ) { // 遍历其中一个对象属性，看看另一个对象对应的属性值是否相同
        if(obj2keys.indexOf(obj1keys[i]) === -1) return false;
        if(obj1[obj1keys[i]] !== obj2[obj1keys[i]]) {
            return false;
        }
    }
    return true;
}
const unique2 = (arr) => {
    let result = [];
    for(let i = 0; i < arr.length; i ++) {
        for(let j = i + 1; j < arr.length; j ++) { // j = i + 1
            if(isEqual(arr[i], arr[j])) { // 两者相同，删除其中一个对象（j）的同时还要j --，因为splice会修改数组，原本j + 1的元素已经到了j的位置
                arr.splice(j, 1);
                j --;
            };
        }
    }
    return arr;
}
console.log(unique(arr));

// 方法三：使用Map + 规范化键值（推荐）
const normalizeObject = (obj) => {
    // 将对象的所有键按字母顺序排序，确保相同内容的对象有相同的键序
    return Object.keys(obj)
        .sort() //不带入参的 sort() 方法会将数组元素转换为字符串，然后按照 Unicode 编码顺序进行排序。
        .reduce((result, key) => {
            result[key] = obj[key];
            return result;
        }, {});
};

/**
 * 说白了就是遍历一遍需要去重的数组，每个数组元素都转成唯一字符串并用map来标记是否已经出现过
 * 以至于如何转成唯一字符串，就是normalizeObject方法
 */
const unique3 = (arr) => {
    const seen = new Map();
    const result = [];
    
    for (const item of arr) {
        // 创建规范化的键值对字符串
        const normalized = JSON.stringify(normalizeObject(item));
        
        if (!seen.has(normalized)) {
            seen.set(normalized, true);
            result.push(item);
        }
    }
    
    return result;
};
</script>
</body>
</html>